/**
 * 测量函数执行耗时的装饰器
 * @param value - 被装饰的函数
 * @param ctx - 装饰器上下文
 * @returns 包装后的函数，会自动计算并输出执行时间
 */
export function measureTime<This, Args extends unknown[], Return>(
  value: (this: This, ...args: Args) => Return,
  ctx: DecoratorContext,
) {
  return function (this: This, ...args: Args): Return {
    const startTime = performance.now();

    try {
      const result = value.apply(this, args);

      // 处理异步函数
      if (result instanceof Promise) {
        return handleAsyncResult(result, ctx, startTime) as Return;
      }

      // 处理同步函数
      logExecutionTime(ctx, startTime);
      return result;
    } catch (error) {
      // 即使出错也记录执行时间
      logExecutionTime(ctx, startTime);
      throw error;
    }
  };
}

/** 全局统计表，使用 WeakMap 存储实例到方法调用计数的映射 */
const countMap = new WeakMap<object, Map<string, number>>();

/**
 * 统计函数调用次数的装饰器
 * @param value - 被装饰的函数
 * @param ctx - 装饰器上下文
 * @returns 包装后的函数，会自动记录调用次数
 */
export function countCalls<This, Args extends unknown[], Return>(
  value: (this: This, ...args: Args) => Return,
  ctx: DecoratorContext,
) {
  // 只处理方法装饰器
  if (ctx.kind !== 'method') {
    return value;
  }

  const methodName = String(ctx.name);

  return function (this: This, ...args: Args): Return {
    const startExecution = () => {
      recordCallCount(this, methodName);
    };

    try {
      const result = value.apply(this, args);

      // 处理异步函数
      if (result instanceof Promise) {
        startExecution();
        return result.catch((error) => {
          throw error;
        }) as Return;
      }

      // 处理同步函数
      startExecution();
      return result;
    } catch (error) {
      // 即使出错也记录调用次数
      startExecution();
      throw error;
    }
  };
}

/**
 * 记录函数调用次数的辅助函数
 * @param instance - 函数所属的实例
 * @param methodName - 方法名称
 */
function recordCallCount(instance: unknown, methodName: string): void {
  try {
    // 严格的类型检查
    if (!isValidInstance(instance)) {
      console.warn(`无法记录调用次数：实例不是有效对象 (${typeof instance})`);
      return;
    }

    // 获取或初始化该实例的统计 Map
    let instanceCounts = countMap.get(instance);
    if (!instanceCounts) {
      instanceCounts = new Map<string, number>();
      countMap.set(instance, instanceCounts);
    }

    // 更新调用计数
    const currentCount = (instanceCounts.get(methodName) ?? 0) + 1;
    instanceCounts.set(methodName, currentCount);

    console.log(`${methodName} 调用次数：${currentCount}`);
  } catch (error) {
    // 确保统计功能异常不影响主要功能
    console.warn('记录调用次数时发生错误：', error);
  }
}

/**
 * 检查实例是否为有效对象
 * @param instance - 待检查的实例
 * @returns 是否为有效的对象实例
 */
function isValidInstance(instance: unknown): instance is object {
  return typeof instance === 'object' && instance !== null;
}
/**
 * 处理异步函数结果
 */
function handleAsyncResult<T>(
  promise: Promise<T>,
  ctx: DecoratorContext,
  startTime: number,
): Promise<T> {
  return promise
    .then((result) => {
      logExecutionTime(ctx, startTime);
      return result;
    })
    .catch((error) => {
      logExecutionTime(ctx, startTime);
      throw error;
    });
}

/**
 * 记录执行时间
 */
function logExecutionTime(ctx: DecoratorContext, startTime: number): void {
  const executionTime = performance.now() - startTime;
  console.log(`${String(ctx.name)} 执行耗时：${executionTime.toFixed(2)}ms`);
}
